package com.mk.service;

import act.controller.Controller;
import act.validation.NotBlank;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.ReUtil;
import com.mk.util.Redis;
import com.mk.domain.CpUser;
import com.mk.enums.CacheKey;
import com.mk.enums.Config;
import com.mk.enums.GlobalValues;
import com.mk.exception.UserException;
import com.mk.msg.M;
import com.mk.msg.template.MsSmsValidateCheck;
import com.mk.properties.AppConfig;
import com.mk.util.S2;
import com.mk.util.VerifyCodeUtils;
import org.apache.commons.lang3.StringUtils;
import org.beetl.sql.core.engine.PageQuery;
import org.osgl.$;
import org.osgl.mvc.result.Result;
import org.osgl.storage.ISObject;
import org.osgl.storage.impl.SObject;
import org.osgl.util.C;
import org.osgl.util.S;
import org.redisson.api.RBucket;

import javax.inject.Inject;
import java.util.*;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("unused")
public class BasePaasService extends Controller.Base {
    private static final String EMPTY = " ";
    private static final String ASC = "ASC";
    private static final String DESC = "DESC";
    @Inject
    private CpUser.Mapper cpUserMapper;

    public Map getConfigJson() {
        $.T2 t = readConfigs();
        return C.Map("GlobalMap", t._1, "GlobalArray", t._2);
    }

    public PageQuery<Map> queryBase(@NotBlank String sqlCode,
                                    String currentPage,
                                    String pageSize,
                                    String sortName,
                                    String sortType,
                                    Map<String, String[]> allParams) {
        //region 参数初始化
        PageQuery<Map> query = new PageQuery<>();
        //endregion

        //region 分页处理
        if (!S.isAnyBlank(pageSize, currentPage)) {
            query.setPageNumber(Integer.valueOf(currentPage));
            query.setPageSize(Integer.valueOf(pageSize));
        } else {
            query.setPageSize(Long.MAX_VALUE);
        }
        //endregion

        //region 处理排序
        String orderStr = "";
        if (S.isNotBlank(sortName)) {
            query.setOrderBy(sortName + EMPTY + S2.electOneNotBlank(sortType, ASC));
        }
        //endregion

        //region 提交的参数
        for (Map.Entry<String, String[]> paramKV : allParams.entrySet()) {
            String key = paramKV.getKey();
            boolean isArray = key.endsWith("[]");
            key = key.replaceAll("\\[\\]", "");
            if (paramKV.getValue().length > 0) {
                if (isArray) {
                    query.setPara(key, paramKV.getValue());
                } else {
                    query.setPara(key, paramKV.getValue()[0]);
                }
            } else {
                query.setPara(key, null);
            }
        }
        //endregion

        //region 查询开始
        cpUserMapper.getSQLManager().pageQuery(sqlCode, Map.class, query);
        //endregion
        return query;
    }

    public PageQuery<Map> query(@NotBlank String sqlCode,
                                String currentPage,
                                String pageSize,
                                String sortName,
                                String sortType) {
        return queryBase(sqlCode, currentPage, pageSize, sortName, sortType, context.allParams());
    }

    public Result createPicCode(String index) {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100, 36);
        String code = VerifyCodeUtils.outputVerifyImage(4);
        Redis.otherDb.getBucket(CacheKey.PICCODE.value() + S2.electOneNotBlank(index, "-"), String.class).set(code, 30, TimeUnit.MINUTES);
//        CacheUtil.cache(context, CacheKey.PICCODE.value() + S2.electOneNotBlank(index, "-"), code);
        byte[] ba = VerifyCodeUtils.outputImage(100, 36, code);
        ISObject sobj = SObject.of(ba);
        sobj.setAttribute(ISObject.ATTR_FILE_NAME, "validatecode.jpg");
        sobj.setAttribute(ISObject.ATTR_CONTENT_TYPE, "image/jpg");
        return binary(sobj);
    }

    public String getSmsCode(String phone) {
        String code = S2.randomNumberString(4);
        Redis.otherDb.getBucket(Config.SMS_CODE.value() + "-" + phone, String.class).set(code, 10, TimeUnit.MINUTES);
        M.excute(new MsSmsValidateCheck() {
            @Override public String product() {
                return AppConfig.dayu.title.get();
            }

            @Override public String code() {
                return code;
            }

            @Override public String phone() {
                return phone;
            }
        });
        System.out.println(phone + ">>>" + code);
        return "1";
    }

    public boolean validateCode(String phone, String code) {
        String codeCache = Redis.otherDb.getBucket(Config.SMS_CODE.value() + "-" + phone, String.class).get();
        if (S.neq(codeCache, code)) {
            throw new UserException("短信验证码错误");
        }
        return true;
    }

    public String serviceTime() {
        return String.valueOf(new Date().getTime());
    }

    public String ip() {
        return context.req().ip();
    }

    private $.T2<Map<String, LinkedHashMap<String, String>>, Map<String, List<List<String>>>> readConfigs() {
        //region 读取
        int i = 0, j = GlobalValues.values().length;
        Map<String, LinkedHashMap<String, String>> result = new HashMap<>();
        Map<String, List<List<String>>> result2 = new HashMap<>();
        while (i < j - 1) {
            i++;
            GlobalValues vv = GlobalValues.values()[i];
            String v_guess = ReUtil.get("_([^_]+)$", vv.name(), 1);
            if (StringUtils.equals(v_guess, vv.value())) {
                String v_name = vv.name().replaceAll("_" + v_guess, "");
                LinkedHashMap<String, String> v;
                List<List<String>> v2;
                if (!result.containsKey(v_name)) {
                    v = new LinkedHashMap<>();
                    v2 = new ArrayList<>();
                    result.put(v_name, v);
                    result2.put(v_name, v2);
                } else {
                    v = result.get(v_name);
                    v2 = result2.get(v_name);
                }
                v.put(vv.value(), vv.desc());
                List<String> vv2 = new ArrayList<>();
                vv2.add(vv.value());
                vv2.add(vv.desc());
                v2.add(vv2);
            }
        }
        return new $.T2<>(result, result2);
    }

    /**
     * JSTOKEN
     *
     * @param token v-token
     * @return newtoken
     */
    public String getJsToken(String token) {
        RBucket<String> oldTokenBucket = Redis.otherDb.getBucket(token, String.class);
        if (oldTokenBucket.isExists()) {
            String tokenNew = S2.UUID();
            oldTokenBucket.delete();
            Redis.otherDb.getBucket(tokenNew, String.class).set(GlobalValues.TEMPLATE_STATE_1.value(), 10, TimeUnit.MINUTES);
            return tokenNew;
        }
        return null;
    }

    /**
     * JSTOKEN new
     *
     * @return token
     */
    public String newJsToken() {
        String tokenNew = S2.UUID();
        Redis.otherDb.getBucket(tokenNew, String.class).set(GlobalValues.TEMPLATE_STATE_1.value(), 10, TimeUnit.MINUTES);
        return tokenNew;
    }
}
